/**
 * SoundPreviewPane.java
 * @author Daniel Liu
 * Create: 2006-12-23 ����01:57:44
 */
package org.lex.ftp.ui.prefs;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Arrays;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.AbstractTableModel;

import org.lex.sound.AudioPlayer;
import org.lex.utils.pool.DaemonExecutor;
import org.lex.utils.text.SizeFormat;
import org.lex.utils.text.SizeUnit;


public class SoundPreviewPane extends JPanel implements ChangeListener, PropertyChangeListener {
	private static final String[] columnNames = { "Name", "Value" };
	private JScrollPane scrollPane = null;
	private JTable table = null;
	private SoundTableModel tableModel = null;
	private JButton playButton = null;
	private JButton stopButton = null;
	private JFileChooser fc = null;
	private JPanel controlPane = null;
	private AudioPlayer player = null;

	public SoundPreviewPane(JFileChooser fc) {
		super();
		this.fc = fc;
		initialize();
		this.fc.addPropertyChangeListener(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY, this);
	}

	/*
	 * ����JFileChooser.SELECTED_FILE_CHANGED_PROPERTY�¼�
	 */
	public void propertyChange(PropertyChangeEvent e) {
		File file = fc.getSelectedFile();
		if (null == file || false == file.isFile()) {
			this.getPlayButton().setEnabled(false);
			return;
		}
		if (false == this.getPlayButton().isEnabled())
			this.getPlayButton().setEnabled(true);
		this.getTableModel().setFile(file);
	}

	/*
	 * ����AudioPlayer���¼�����AudioPlayer״̬����ı�ʱ��õ�֪ͨ
	 * e.getSource()�Ƿ����¼���AuduiPlayer
	 */
	public void stateChanged(ChangeEvent e) {
		if (true == player.isPlaying()) {
			playButton.setEnabled(false);
			stopButton.setEnabled(true);
		} else {
			playButton.setEnabled(true);
			stopButton.setEnabled(false);
		}
	}

	private void initialize() {
		BorderLayout layout = new BorderLayout();
		layout.setVgap(5);
		this.setLayout(layout);
		this.add(getControlPane(), BorderLayout.NORTH);
		this.add(getScrollPane(), BorderLayout.CENTER);
		this.add(Box.createHorizontalStrut(6), BorderLayout.WEST);
		this.add(Box.createHorizontalStrut(5), BorderLayout.EAST);
	}

	private JPanel getControlPane() {
		if (controlPane == null) {
			FlowLayout flowLayout = new FlowLayout();
			flowLayout.setHgap(11);
			flowLayout.setVgap(0);
			controlPane = new JPanel();
			controlPane.setLayout(flowLayout);
			controlPane.add(getPlayButton(), null);
			controlPane.add(getStopButton(), null);
		}
		return controlPane;
	}

	private JButton getPlayButton() {
		if (playButton == null) {
			playButton = new JButton();
			playButton.setText("Play");
			playButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					File file = getTableModel().getFile();
					if (null == file)
						return;
					player = AudioPlayer.newPlayer(file);
					player.addChangeListener(SoundPreviewPane.this);
					DaemonExecutor.execute(player);
				}
			});
		}
		return playButton;
	}

	private JButton getStopButton() {
		if (stopButton == null) {
			stopButton = new JButton();
			stopButton.setText("Stop");
			stopButton.setEnabled(false);
			stopButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					if (null != player)
						player.stop();
				}
			});
		}
		return stopButton;
	}

	private JScrollPane getScrollPane() {
		if (scrollPane == null) {
			scrollPane = new JScrollPane();
			scrollPane.setViewportView(getTable());
		}
		return scrollPane;
	}

	private JTable getTable() {
		if (table == null) {
			table = new JTable();
			table.setModel(this.getTableModel());
		}
		return table;
	}

	private SoundTableModel getTableModel() {
		if (null == tableModel) {
			tableModel = new SoundTableModel();
		}
		return tableModel;
	}

	class SoundTableModel extends AbstractTableModel {
		private File file = null;
		private String[] properties = null;
		private Object[] values = null;

		public SoundTableModel() {
			super();
			this.properties = new String[] { "File", "Size", "Bitrate", "Channels", "Frame Rate", "Encoding" };
			this.values = new Object[this.properties.length];
		}

		public void setFile(File file) {
			this.file = file;
			Arrays.fill(values, null);
			if (null == file || false == file.exists() || false == file.isFile()) {
				this.fireTableDataChanged();
				return;
			}
			values[0] = file.getName();
			values[1] = file.length() + " bytes";
			try {
				AudioInputStream ais = AudioSystem.getAudioInputStream(file);
				AudioFormat af = ais.getFormat();
				values[2] = SizeFormat.format(file.length() / af.getSampleSizeInBits(), SizeUnit.K).toLowerCase() + "bps";
				values[3] = af.getChannels();
				values[4] = af.getFrameRate() + " Hz";
				values[5] = af.getEncoding();
			} catch (Exception e) {
			}
			this.fireTableDataChanged();
		}

		public File getFile() {
			return this.file;
		}

		@Override
		public String getColumnName(int column) {
			return columnNames[column];
		}

		public int getColumnCount() {
			return columnNames.length;
		}

		public int getRowCount() {
			return values.length;
		}

		public Object getValueAt(int row, int column) {
			if (0 == column)
				return this.properties[row];
			else
				return values[row];
		}
	}
}
